#ifndef __IP_HPP__
#define __IP_HPP__

#include <stdint.h>
#include <stdlib.h>
#include <memory.h>
#include <iostream>
#include <string>
#include <sstream>
#include <iostream>
#include <string>
#include <sstream>

#include "GenericException.hpp"

/**
 * An IPv4 address
 */
class IP {

	private:
		unsigned char address[4]; /**< underlying byte buffer storing the 4 octets of an IP address */

	public:
		IP() : address() {
			setTo(0, 0, 0, 0);
		}

		IP(const std::string& address) {
			setTo(address);
		}

		void setTo(const std::string& address) {
			std::istringstream iss(address);
			std::string octet1s, octet2s, octet3s, octet4s;
			if (!getline(iss, octet1s, '.')) GENERICSTRMEXCEPTION(address << " is no valid IPv4 address.");
			if (!getline(iss, octet2s, '.')) GENERICSTRMEXCEPTION(address << " is no valid IPv4 address.");
			if (!getline(iss, octet3s, '.')) GENERICSTRMEXCEPTION(address << " is no valid IPv4 address.");
			if (!getline(iss, octet4s, '.')) GENERICSTRMEXCEPTION(address << " is no valid IPv4 address.");
			unsigned char octet1, octet2, octet3, octet4;
			octet1 = atoi(octet1s.c_str());
			octet2 = atoi(octet2s.c_str());
			octet3 = atoi(octet3s.c_str());
			octet4 = atoi(octet4s.c_str());
			setTo(octet1, octet2, octet3, octet4);
		}

		void setTo(unsigned char address1, unsigned char address2, unsigned char address3, unsigned char address4) {
			this->address[0] = address1;
			this->address[1] = address2;
			this->address[2] = address3;
			this->address[3] = address4;
		}

		void setTo(const char* address) {
			memcpy(this->address, address, 4);
		}

		uint32_t getInt() const {
			return (address[0] << 24) | (address[1] << 16) | (address[2] << 8) | (address[3] << 0);
		}

		const unsigned char* getMemory() const {
			return address;
		}

		std::string getStr() const {
			std::stringstream Strm;
			Strm << (int)address[0] << "." << (int)address[1] << "." << (int)address[2] << "." << (int)address[3];
			return Strm.str();
		}

		bool isZero() const {
			return (address[0] == 0) &&
			       (address[1] == 0) &&
			       (address[2] == 0) &&
			       (address[3] == 0);
		}

		~IP() {
		}

};
#endif

